package com.css.fxfzysx.modules.vabStructure.service.impl;

import com.css.fxfzysx.base.response.RestResponse;
import com.css.fxfzysx.common.utils.BeanUtil;
import com.css.fxfzysx.constants.FxfzConstants;
import com.css.fxfzysx.modules.cztDataMange.entity.CbvInfoCurveValueEntity;
import com.css.fxfzysx.modules.cztDataMange.entity.CbvInfoEntity;
import com.css.fxfzysx.modules.cztDataMange.entity.CbvInfoMatrixValueEntity;
import com.css.fxfzysx.modules.cztDataMange.entity.CpvResultEntity;
import com.css.fxfzysx.modules.cztDataMange.repository.BacInformationRepository;
import com.css.fxfzysx.modules.cztDataMange.service.impl.BacInformationServiceImpl;
import com.css.fxfzysx.modules.vabStructure.constans.FimEnum;
import com.css.fxfzysx.modules.vabStructure.constans.StructureTypeConstant;
import com.css.fxfzysx.modules.vabStructure.entity.CztBuildingMatrixEntity;
import com.css.fxfzysx.modules.vabStructure.param.CustomVulnerabilityParam;
import com.css.fxfzysx.modules.vabStructure.param.EstimateParam;
import com.css.fxfzysx.modules.vabStructure.param.MatchingParam;
import com.css.fxfzysx.modules.vabStructure.repository.CustomVulnerabilityRepository;
import com.css.fxfzysx.modules.vabStructure.repository.SvAnalysisRepository;
import com.css.fxfzysx.modules.vabStructure.service.CustomVulnerabilityService;
import com.css.fxfzysx.modules.vabStructure.vo.BuildingVulnerabilityVo;
import com.css.fxfzysx.modules.vabStructure.vo.CurveVo;
import com.css.fxfzysx.modules.vabStructure.vo.GenerateVulnerabilityMatrixVo;
import com.css.fxfzysx.util.CreateGson;
import com.css.fxfzysx.util.PlatformObjectUtils;
import com.css.fxfzysx.util.PlatformPageUtils;
import com.css.fxfzysx.web.PlatformSessionContext;
import com.css.fxfzysx.zcpt.sys.entity.SUser;
import com.css.fxfzysx.zcpt.sys.service.SUserService;
import com.css.fxfzysx.zcpt.sys.service.SysAreaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CustomVulnerabilityServiceImpl implements CustomVulnerabilityService {

    @Autowired
    private CustomVulnerabilityRepository customVulnerabilityRepository;

    @Autowired
    private SvAnalysisRepository svAnalysisRepository;

    @Autowired
    private SvAnalysisServiceImpl svAnalysisService;

    @Autowired
    private BacInformationRepository bacInformationRepository;

    @Autowired
    private SUserService userService;

    @Autowired
    private SysAreaService areaService;

    @Override
    public RestResponse queryData(CbvInfoEntity cbvInfoEntity, HttpServletRequest request) {
        try {
            int page = Integer.valueOf(request.getParameter(PlatformPageUtils.CUR_PAGE));
            int size = Integer.valueOf(request.getParameter(PlatformPageUtils.PAGE_SIZE));
            if (PlatformObjectUtils.isEmpty(cbvInfoEntity.getProvince())) {
                String user = userService.getSUser(PlatformSessionContext.getUserID());
                SUser sUser = CreateGson.createGson().fromJson(user, SUser.class);
                String province = areaService.getAreaNameByAreaId(sUser.getProvinceId());
                cbvInfoEntity.setProvince(province);
            }
            return RestResponse.succeed(customVulnerabilityRepository.queryData(cbvInfoEntity, page, size));
        } catch (Exception e) {
            String errorMessage = "查看失败!";
            log.error(errorMessage, e);
            return RestResponse.fail(errorMessage);
        }
    }

    @Override
    public RestResponse moveBasicLibrary(CustomVulnerabilityParam param) {
        try {
            if (param.getOperate().equals("0")) {
                customVulnerabilityRepository.moveBasicLibrary(param.getId(), param.getOperate(), param.getProvince());
            } else {
                Integer count = customVulnerabilityRepository.queryBasicLibrary(param);
                if (count != 0) {
                    return RestResponse.fail("失败,存在重复数据!");
                } else {
                    customVulnerabilityRepository.moveBasicLibrary(param.getId(), param.getOperate(), param.getProvince());
                }
            }
            return RestResponse.succeed("成功!");
        } catch (Exception e) {
            String errorMessage = "失败!";
            log.error(errorMessage, e);
            return RestResponse.fail(errorMessage);
        }
    }

    @Override
    public RestResponse generateMatrix(String cbviId, String province) {
        try {
            CbvInfoEntity entity = customVulnerabilityRepository.getBasicLibraryById(cbviId, province);
            HashMap<String, Object> resultMap = new HashMap<>();
            Integer type = entity.getCurveOrMatrix();
            //type    0曲线  1矩阵
            if (type == 0) {
                List<CbvInfoCurveValueEntity> dataList = customVulnerabilityRepository.getCureByCbviId(cbviId);
                resultMap.put("curve", dataList);
            } else {
                ArrayList<GenerateVulnerabilityMatrixVo> matrix = getMatrix(cbviId);
                resultMap.put("matrix", matrix);
            }
            return RestResponse.succeed(resultMap);
        } catch (Exception e) {
            String errorMessage = "失败!";
            log.error(errorMessage, e);
            return RestResponse.fail(errorMessage);
        }
    }


    private ArrayList<GenerateVulnerabilityMatrixVo> getMatrix(String cbviId) {
        ArrayList<GenerateVulnerabilityMatrixVo> matrixDataList = new ArrayList<>();
        List<CbvInfoMatrixValueEntity> dataList = customVulnerabilityRepository.getMatrixByCbvId(cbviId);
        dataList.forEach(ma -> {
            GenerateVulnerabilityMatrixVo entity1 = new GenerateVulnerabilityMatrixVo();
            entity1.setDamage("基本完好");
            entity1.setIntensity(ma.getIntensity());
            entity1.setRate(ma.getBasicallyIntact().toString() + "%");
            matrixDataList.add(entity1);
            GenerateVulnerabilityMatrixVo entity2 = new GenerateVulnerabilityMatrixVo();
            entity2.setDamage("轻微破坏");
            entity2.setIntensity(ma.getIntensity());
            entity2.setRate(ma.getMinorDamage().toString() + "%");
            matrixDataList.add(entity2);
            GenerateVulnerabilityMatrixVo entity3 = new GenerateVulnerabilityMatrixVo();
            entity3.setDamage("中等破坏");
            entity3.setIntensity(ma.getIntensity());
            entity3.setRate(ma.getModerateDamage().toString() + "%");
            matrixDataList.add(entity3);
            GenerateVulnerabilityMatrixVo entity4 = new GenerateVulnerabilityMatrixVo();
            entity4.setDamage("严重破坏");
            entity4.setIntensity(ma.getIntensity());
            entity4.setRate(ma.getSeriousDamage().toString() + "%");
            matrixDataList.add(entity4);
            GenerateVulnerabilityMatrixVo entity5 = new GenerateVulnerabilityMatrixVo();
            entity5.setDamage("倒塌");
            entity5.setIntensity(ma.getIntensity());
            entity5.setRate(ma.getCollapse().toString() + "%");
            matrixDataList.add(entity5);
        });
        return matrixDataList;
    }

    @Override
    public RestResponse dataMatching(MatchingParam param) {
        try {
            //时间格式化
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            //从数据库查出来矩阵数据    生成的易损性数据 and 概率地震矩阵或曲线 and 易损性信息矩阵或曲线
            List<CbvInfoEntity> basicLibraryList = customVulnerabilityRepository.queryBasicLibraryData(param);
            HashMap<String, List<GenerateVulnerabilityMatrixVo>> resultMap = new HashMap<>();
            HashMap<String, List<GenerateVulnerabilityMatrixVo>> resultMap1 = new HashMap<>();
            if (PlatformObjectUtils.isNotEmpty(basicLibraryList)) {
                for (CbvInfoEntity it : basicLibraryList) {
                    //生成的易损性数据
                    if (it.getDataType().equals(FxfzConstants.CZT_SCYSX_INFO)) {
                        List<GenerateVulnerabilityMatrixVo> dataList = null;
                        CztBuildingMatrixEntity entity = svAnalysisRepository.getBuildingMatrixById(it.getPId());
                        String spilt = SvAnalysisServiceImpl.spilt(entity.getDataSourcesIds());
                        String[] intensityArr = {"6度", "7度", "8度", "9度", "10度"};
                        //震害数据矩阵
                        if (entity.getMatrixType() == 1) {
                            dataList = svAnalysisService.getDataList(spilt, intensityArr);
                            if (PlatformObjectUtils.isNotEmpty(param.getType()) && param.getType() == 1) {
                                List<GenerateVulnerabilityMatrixVo> maxMatrix = getMaxMatrix(dataList);
                                resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), maxMatrix);
                            } else {
                                resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), dataList);
                            }
                        }
                        // 2 预测数据矩阵  3 筛选数据矩阵
                        if (entity.getMatrixType() == 2 || entity.getMatrixType() == 3) {
                            dataList = svAnalysisService.getPredictiveData(spilt, intensityArr, entity.getMatrixType());
                            if (PlatformObjectUtils.isNotEmpty(param.getType()) && param.getType() == 1) {
                                List<GenerateVulnerabilityMatrixVo> maxMatrix = getMaxMatrix(dataList);
                                resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), maxMatrix);
                            } else {
                                resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), dataList);
                            }
                        }
                    }
                    //概率地震
                    if (it.getDataType().equals(FxfzConstants.CZT_GLDZ_INFO)) {
                        List<CpvResultEntity> dataList = bacInformationRepository.getCpvResultEntityByCpviId(it.getPId());
                        ArrayList<CbvInfoCurveValueEntity> curveList = new ArrayList<>();
                        dataList.forEach(gv -> {
                            CbvInfoCurveValueEntity entity = new CbvInfoCurveValueEntity();
                            entity.setBreakState(gv.getBreakState());
                            entity.setFim(gv.getFim());
                            entity.setIm(gv.getIm());
                            curveList.add(entity);
                        });
                        List<GenerateVulnerabilityMatrixVo> resultData = getProcessData(curveList);
                        if (PlatformObjectUtils.isNotEmpty(param.getType()) && param.getType() == 1) {
                            List<GenerateVulnerabilityMatrixVo> maxMatrix = getMaxMatrix(resultData);
                            resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), maxMatrix);
                        } else {
                            resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), resultData);
                        }
                    }
                    //易损性信息
                    if (it.getDataType().equals(FxfzConstants.CZT_JZWYSX_INFO)) {
                        List<CbvInfoMatrixValueEntity> matrixList = svAnalysisRepository.getInfoMatrixById(it.getPId());
                        ArrayList<GenerateVulnerabilityMatrixVo> matrixDataList = new ArrayList<>();
                        if (matrixList != null) {
                            matrixList.forEach(ma -> {
                                GenerateVulnerabilityMatrixVo entity1 = new GenerateVulnerabilityMatrixVo();
                                entity1.setDamage("基本完好");
                                entity1.setIntensity(ma.getIntensity());
                                entity1.setRate(ma.getBasicallyIntact().toString() + "%");
                                matrixDataList.add(entity1);
                                GenerateVulnerabilityMatrixVo entity2 = new GenerateVulnerabilityMatrixVo();
                                entity2.setDamage("轻微破坏");
                                entity2.setIntensity(ma.getIntensity());
                                entity2.setRate(ma.getMinorDamage().toString() + "%");
                                matrixDataList.add(entity2);
                                GenerateVulnerabilityMatrixVo entity3 = new GenerateVulnerabilityMatrixVo();
                                entity3.setDamage("中等破坏");
                                entity3.setIntensity(ma.getIntensity());
                                entity3.setRate(ma.getModerateDamage().toString() + "%");
                                matrixDataList.add(entity3);
                                GenerateVulnerabilityMatrixVo entity4 = new GenerateVulnerabilityMatrixVo();
                                entity4.setDamage("严重破坏");
                                entity4.setIntensity(ma.getIntensity());
                                entity4.setRate(ma.getSeriousDamage().toString() + "%");
                                matrixDataList.add(entity4);
                                GenerateVulnerabilityMatrixVo entity5 = new GenerateVulnerabilityMatrixVo();
                                entity5.setDamage("倒塌");
                                entity5.setIntensity(ma.getIntensity());
                                entity5.setRate(ma.getCollapse().toString() + "%");
                                matrixDataList.add(entity5);
                            });
                            if (PlatformObjectUtils.isNotEmpty(param.getType()) && param.getType() == 1) {
                                List<GenerateVulnerabilityMatrixVo> maxMatrix = getMaxMatrix(matrixDataList);
                                resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), maxMatrix);
                            } else {
                                resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), matrixDataList);
                            }
                        }
                    }
                }
                //如果没有勾选年代，层数，用途这三个条件，那么就用手动输入的数据
                if (PlatformObjectUtils.isNotEmpty(param.getYearsList()) || PlatformObjectUtils.isNotEmpty(param.getCsList()) ||
                        PlatformObjectUtils.isNotEmpty(param.getUseList())) {
                    List<BigDecimal> calculate = calculate(getCalculateValue(param));
                    ArrayList<GenerateVulnerabilityMatrixVo> value = getValue(calculate, resultMap);
                    if (value.size() == 0) {
                        return RestResponse.fail("基础库中缺少部分易损性矩阵，无法匹配，请管理员前往易损性基础库中维护易损性矩阵。");
                    } else {
                        if (PlatformObjectUtils.isNotEmpty(param.getType()) && param.getType() == 1) {
                            //返回给产品信息的
                            List<GenerateVulnerabilityMatrixVo> maxMatrix = getMaxMatrix(value);
                            resultMap1.put("countValue", maxMatrix);
                        } else {
                            resultMap1.put("countValue", value);
                        }
                    }
                }
            }
            if (PlatformObjectUtils.isEmpty(param.getYearsList()) && PlatformObjectUtils.isEmpty(param.getCsList()) && PlatformObjectUtils.isEmpty(param.getUseList())) {
                return RestResponse.succeed(resultMap);
            } else {
                return RestResponse.succeed(resultMap1);
            }
        } catch (Exception e) {
            String errorMessage = "失败!";
            log.error(errorMessage, e);
            return RestResponse.fail(errorMessage);
        }
    }

    /**
     * 处理计算所需要的数据
     *
     * @return
     */
    private ArrayList<List<BigDecimal>> getCalculateValue(MatchingParam param) {
        ArrayList<List<BigDecimal>> valueList = new ArrayList<>();
        if (PlatformObjectUtils.isNotEmpty(param.getUseList())) {
            valueList.add(param.getUseList());
        }
        if (PlatformObjectUtils.isNotEmpty(param.getCsList())) {
            valueList.add(param.getCsList());
        }
        if (PlatformObjectUtils.isNotEmpty(param.getYearsList())) {
            valueList.add(param.getYearsList());
        }
        return valueList;
    }

    /**
     * 获取一个矩阵不同烈度下的最大值
     *
     * @param value
     * @return
     */
    private static List<GenerateVulnerabilityMatrixVo> getMaxMatrix(List<GenerateVulnerabilityMatrixVo> value) {
        Map<Object, List<GenerateVulnerabilityMatrixVo>> collect = value.stream().collect(Collectors.groupingBy(GenerateVulnerabilityMatrixVo::getIntensity));
        ArrayList<GenerateVulnerabilityMatrixVo> list = new ArrayList<>();

        collect.forEach((k, v) -> {
            GenerateVulnerabilityMatrixVo entity = new GenerateVulnerabilityMatrixVo();
            //取最大值
            Optional<GenerateVulnerabilityMatrixVo> voList = v.stream()
                    .max(Comparator.comparingDouble(data -> parsePercentage(data.getRate())));
            //如果为空，返回null
            GenerateVulnerabilityMatrixVo maxEntity = voList.orElse(null);
            if (PlatformObjectUtils.isNotEmpty(maxEntity)) {
                entity.setIntensity(k.toString());
                entity.setDamage(maxEntity.getDamage());
                entity.setRate(maxEntity.getRate());
                list.add(entity);
            }
        });
        return list;
    }

    /**
     * 解析百分比值，去掉百分号并转换为double类型
     */
    private static double parsePercentage(String range) {
        return Double.parseDouble(range.replace("%", ""));
    }


    /**
     * 计算每个条件的值，如：年代一共需要6个参数值，现在list中只有一个，那么就用1-这个参数，得出来的值除以5
     *
     * @param list
     * @param size
     * @return
     */
    private static List<BigDecimal> countValue(List<BigDecimal> list, int size, BigDecimal num) {
        if (list == null) {
            list = new ArrayList<>();
        }
        if (list.size() != size) {
            BigDecimal sum = list.stream()
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(4, RoundingMode.HALF_UP);
            BigDecimal subtract = num.subtract(sum);
            BigDecimal divide = subtract.divide(new BigDecimal(size - list.size()), 4, RoundingMode.HALF_UP);
            while (list.size() != size) {
                list.add(divide);
            }
        }
        return list;
    }

    /**
     * 处理用途数据
     *
     * @param value
     * @param size
     * @param num
     * @return
     */
    private List<BigDecimal> countUseValue(BigDecimal value, int size, BigDecimal num) {
        ArrayList<BigDecimal> list = new ArrayList<>();
        BigDecimal subtract = num.subtract(value);
        BigDecimal divide = subtract.divide(BigDecimal.valueOf(size), 4, RoundingMode.HALF_UP);
        while (list.size() != size) {
            list.add(divide);
        }
        return list;
    }

    /**
     * 两个list中的值相乘（每个都乘一遍） 然后求和
     *
     * @return
     */
    private static ArrayList<GenerateVulnerabilityMatrixVo> getValue(List<BigDecimal> list1, HashMap<String, List<GenerateVulnerabilityMatrixVo>> map) {
        ArrayList<GenerateVulnerabilityMatrixVo> resultVo = new ArrayList<>();
        ArrayList<GenerateVulnerabilityMatrixVo> list = new ArrayList<>();
        map.forEach((k, v) -> {
            list.addAll(v);
        });
        Map<String, List<GenerateVulnerabilityMatrixVo>> collect = list.stream().collect(Collectors.groupingBy(GenerateVulnerabilityMatrixVo::getIntensity));
        collect.forEach((k, v) -> {
            Map<String, List<GenerateVulnerabilityMatrixVo>> collect1 = v.stream().collect(Collectors.groupingBy(GenerateVulnerabilityMatrixVo::getDamage));
            collect1.forEach((key, val) -> {
                GenerateVulnerabilityMatrixVo vo = new GenerateVulnerabilityMatrixVo();
                BigDecimal sum = BigDecimal.ZERO;
                if (list1.size() != val.size()) {
                    return;
                }
                for (int i = 0; i < val.size(); i++) {
                    BigDecimal product = new BigDecimal(val.get(i).getRate().replace("%", "")).multiply(list1.get(i));
                    sum = sum.add(product);
                }
                vo.setRate(sum.setScale(2, RoundingMode.HALF_UP) + "%");
                vo.setIntensity(k);
                vo.setDamage(key);
                resultVo.add(vo);
            });
        });
        return resultVo;
    }

    /**
     * 递归计算     a1*b1*c1   a1*b1*c2.............
     *
     * @param lists
     * @return
     */
    private static List<BigDecimal> calculate(List<List<BigDecimal>> lists) {
        int size = lists.size();
        if (size == 0) {
            return new ArrayList<>();
        } else if (size == 1) {
            return lists.get(0);
        } else {
            List<BigDecimal> currentList = lists.get(0);
            List<List<BigDecimal>> subLists = lists.subList(1, size);
            List<BigDecimal> subResults = calculate(subLists);
            List<BigDecimal> results = new ArrayList<>();
            for (BigDecimal currentNumber : currentList) {
                for (BigDecimal subResult : subResults) {
                    results.add(currentNumber.multiply(subResult).setScale(10, RoundingMode.HALF_UP));
                }
            }
            return results;
        }
    }

    @Override
    public void exportData(HttpServletResponse response, String cbviId) {
        ArrayList<GenerateVulnerabilityMatrixVo> matrix = getMatrix(cbviId);
        svAnalysisService.exportMatrixUtil(response, matrix);
    }

    @Override
    public RestResponse curveMatrixTransformation(String id, String province) {
        CbvInfoEntity cbvInfoEntity = bacInformationRepository.getCbvInfoById(id, province);
        if (cbvInfoEntity.getCurveOrMatrix() == 1) {
            //矩阵转曲线
            List<CbvInfoMatrixValueEntity> dataList = customVulnerabilityRepository.getMatrixByCbvId(id);
            List<CurveVo> resultData = turningCurve(dataList);
            return RestResponse.succeed(resultData);
        } else {
            //曲线转矩阵
            List<CbvInfoCurveValueEntity> dataList = customVulnerabilityRepository.getCureByCbviId(id);
            List<GenerateVulnerabilityMatrixVo> resultData = getProcessData(dataList);
            return RestResponse.succeed(resultData);
        }
    }

    /**
     * 计算Fim
     */
    public static List<CurveVo> getFim(List<BigDecimal> imList, BigDecimal mrd, BigDecimal brd, String breakState) {
        //TODO 待修改
//        imList = new ArrayList<>();
//        for (double i = 0.01; i <= 1; i += 0.05) {
//            imList.add(BigDecimal.valueOf(i).setScale(2, RoundingMode.HALF_UP));
//        }
        ArrayList<CurveVo> list = new ArrayList<>();
        AtomicInteger i = new AtomicInteger(1);
        imList.forEach(im -> {
            CurveVo curveVo = new CurveVo();
            BigDecimal logIm = BigDecimal.valueOf(Math.log(im.doubleValue()));
            BigDecimal fim = null;
            fim = logIm.subtract(BigDecimal.valueOf(Math.log(mrd.doubleValue()))).divide(brd, 4,
                    RoundingMode.HALF_UP);
            BigDecimal resultFim = BacInformationServiceImpl.selfCaculate(fim);
            String damage = "";
            switch (breakState) {
                case "轻微破坏":
                    damage = "SD";
                    break;
                case "中等破坏":
                    damage = "MD";
                    break;
                case "严重破坏":
                    damage = "ED";
                    break;
                case "倒塌":
                    damage = "CD";
            }
            if (!breakState.equals("基本完好")) {
                curveVo.setIm(im);
                curveVo.setSerialNumber(i.get());
                curveVo.setBreakState(damage);
                curveVo.setFim(resultFim.setScale(4, RoundingMode.UP));
                list.add(curveVo);
                i.addAndGet(1);
            }
        });
        return list;
    }

    /**
     * 去除百分号
     */
    public static BigDecimal removalPercentage(String reate) {
        String result = reate.replace("%", "");
        return new BigDecimal(result).divide(BigDecimal.valueOf(100), 4, RoundingMode.UP);
    }

    /**
     * 查fai表
     */
    private static BigDecimal getFai(BigDecimal value) {
        // 创建一个标准正态分布对象
        NormalDistribution normalDistribution = new NormalDistribution(0, 1);
        // 使用 inverseCumulativeProbability 方法获取对应的 x 值
        double result = normalDistribution.inverseCumulativeProbability(value.doubleValue());
        return BigDecimal.valueOf(result);
    }

    public static List<GenerateVulnerabilityMatrixVo> getProcessData(List<CbvInfoCurveValueEntity> dataList) {

        ArrayList<GenerateVulnerabilityMatrixVo> resultList = new ArrayList<>();

        BigDecimal[] ims = {BigDecimal.valueOf(0.05), BigDecimal.valueOf(0.1), BigDecimal.valueOf(0.2), BigDecimal.valueOf(0.4), BigDecimal.valueOf(0.8)};

        for (BigDecimal im : ims) {
            String intensity = "";
            if (im.compareTo(BigDecimal.valueOf(0.05)) == 0) {
                intensity = "6度";
            }
            if (im.compareTo(BigDecimal.valueOf(0.1)) == 0) {
                intensity = "7度";
            }
            if (im.compareTo(BigDecimal.valueOf(0.2)) == 0) {
                intensity = "8度";
            }
            if (im.compareTo(BigDecimal.valueOf(0.4)) == 0) {
                intensity = "9度";
            }
            if (im.compareTo(BigDecimal.valueOf(0.8)) == 0) {
                intensity = "10度";
            }

            BigDecimal sd = BigDecimal.ZERO;
            BigDecimal md = BigDecimal.ZERO;
            BigDecimal ed = BigDecimal.ZERO;
            BigDecimal c = BigDecimal.ZERO;
            for (CbvInfoCurveValueEntity it : dataList) {
                if (it.getIm().compareTo(im) == 0) {
                    if (it.getBreakState().equals("SD")) {
                        sd = it.getFim().multiply(new BigDecimal(100));
                    }
                    if (it.getBreakState().equals("MD")) {
                        md = it.getFim().multiply(new BigDecimal(100));
                    }
                    if (it.getBreakState().equals("ED")) {
                        ed = it.getFim().multiply(new BigDecimal(100));
                    }
                    if (it.getBreakState().equals("CD")) {
                        c = it.getFim().multiply(new BigDecimal(100));
                    }
                }
            }
            GenerateVulnerabilityMatrixVo cVo = new GenerateVulnerabilityMatrixVo();
            cVo.setIntensity(intensity);
            cVo.setDamage("倒塌");
            cVo.setRate(c + "%");
            resultList.add(cVo);

            GenerateVulnerabilityMatrixVo edVo = new GenerateVulnerabilityMatrixVo();
            edVo.setIntensity(intensity);
            edVo.setDamage("严重破坏");
            BigDecimal ed1 = ed.subtract(c);
            edVo.setRate(ed1 + "%");
            resultList.add(edVo);

            GenerateVulnerabilityMatrixVo mdVo = new GenerateVulnerabilityMatrixVo();
            mdVo.setIntensity(intensity);
            mdVo.setDamage("中等破坏");
            BigDecimal md1 = md.subtract(ed);
            mdVo.setRate(md1 + "%");
            resultList.add(mdVo);

            GenerateVulnerabilityMatrixVo sdVo = new GenerateVulnerabilityMatrixVo();
            sdVo.setIntensity(intensity);
            sdVo.setDamage("轻微破坏");
            BigDecimal sd1 = sd.subtract(md);
            sdVo.setRate(sd1 + "%");
            resultList.add(sdVo);

            GenerateVulnerabilityMatrixVo basicallyIntactVo = new GenerateVulnerabilityMatrixVo();
            basicallyIntactVo.setIntensity(intensity);
            basicallyIntactVo.setDamage("基本完好");
            BigDecimal basicallyIntactValue = BigDecimal.valueOf(100).subtract(sd1).subtract(ed1).subtract(md1).subtract(c);
            basicallyIntactVo.setRate(basicallyIntactValue + "%");
            resultList.add(basicallyIntactVo);
        }
        return resultList;
    }

    /**
     * 矩阵转曲线
     *
     * @param dataList
     * @return
     */
    public static List<CurveVo> turningCurve(List<CbvInfoMatrixValueEntity> dataList) {
        ArrayList<CurveVo> resultList = new ArrayList<>();
        Map<String, List<CbvInfoMatrixValueEntity>> collect = dataList.stream().collect(Collectors.groupingBy(CbvInfoMatrixValueEntity::getIntensity));
        collect.forEach((k, v) -> {
            for (CbvInfoMatrixValueEntity entity : v) {
                CurveVo cVo = new CurveVo();
                cVo.setBreakState("CD");
                cVo.setIm(FimEnum.getByCode(entity.getIntensity()));
                cVo.setFim(entity.getCollapse().divide(new BigDecimal("100").setScale(6, RoundingMode.HALF_UP)));
                resultList.add(cVo);
                CurveVo edVo = new CurveVo();
                edVo.setBreakState("ED");
                edVo.setIm(FimEnum.getByCode(entity.getIntensity()));
                BigDecimal fim = entity.getCollapse().add(entity.getSeriousDamage());
                edVo.setFim(fim.divide(new BigDecimal("100")).setScale(6, RoundingMode.HALF_UP));
                resultList.add(edVo);
                CurveVo mdVo = new CurveVo();
                mdVo.setBreakState("MD");
                mdVo.setIm(FimEnum.getByCode(entity.getIntensity()));
                BigDecimal mdFim = entity.getCollapse().add(entity.getSeriousDamage()).add(entity.getModerateDamage());
                mdVo.setFim(mdFim.divide(new BigDecimal("100")).setScale(6, RoundingMode.HALF_UP));
                resultList.add(mdVo);
                CurveVo sdVo = new CurveVo();
                sdVo.setBreakState("SD");
                sdVo.setIm(FimEnum.getByCode(entity.getIntensity()));
                BigDecimal sdFim = entity.getCollapse().add(entity.getSeriousDamage()).add(entity.getModerateDamage()).add(entity.getMinorDamage());
                sdVo.setFim(sdFim.divide(new BigDecimal("100")).setScale(6, RoundingMode.HALF_UP));
                resultList.add(sdVo);
            }
        });
        return resultList;
    }

    public static HashMap<String, BigDecimal> getMrdAndBrm(List<BigDecimal> xValues, List<BigDecimal> yValues) {
        ArrayList<BigDecimal> faiList = new ArrayList<>();
        ArrayList<BigDecimal> logList = new ArrayList<>();
        ArrayList<BigDecimal> x2 = new ArrayList<>();

        //x的值
        for (BigDecimal xValue : xValues) {
            BigDecimal fai = BigDecimal.ZERO;
            if (xValue.compareTo(BigDecimal.ZERO) == 0) {
                fai = BigDecimal.valueOf(-3.9);
            } else if (xValue.compareTo(BigDecimal.valueOf(1)) == 0) {
                fai = BigDecimal.valueOf(-4.9);
            } else {
                fai = getFai(xValue);
            }
            faiList.add(fai);
        }

        //y的值
        for (BigDecimal yValue : yValues) {
            double log = Math.log(yValue.doubleValue());
            logList.add(BigDecimal.valueOf(log));
        }

        //求x的平均值
        BigDecimal xAverageValue = faiList.stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(faiList.size()), 2, RoundingMode.HALF_UP);

        //求y的平均值
        BigDecimal yAverageValue = logList.stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(faiList.size()), 2, RoundingMode.HALF_UP);


        ArrayList<BigDecimal> newXList = new ArrayList<>();
        faiList.forEach(fai -> {
            BigDecimal subtract = fai.subtract(xAverageValue);
            x2.add(subtract.pow(2));
            newXList.add(subtract);
        });

        ArrayList<BigDecimal> newYList = new ArrayList<>();
        logList.forEach(log -> {
            BigDecimal subtract = log.subtract(yAverageValue);
            newYList.add(subtract);
        });

        //相乘
        ArrayList<BigDecimal> bigDecimals = new ArrayList<>();
        if (newXList.size() == newYList.size()) {
            for (int i = 0; i < newYList.size(); i++) {
                BigDecimal multipliedValue = newYList.get(i).multiply(newXList.get(i));
                bigDecimals.add(multipliedValue);
            }
        }

        //求和
        BigDecimal sum = bigDecimals.stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal sum1 = x2.stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        //b1
        BigDecimal bRd = null;
        try {
            bRd = sum.divide(sum1, 4, RoundingMode.HALF_UP);
        } catch (Exception e) {
            bRd = BigDecimal.ZERO;
        }
        //b0
        BigDecimal b0 = yAverageValue.subtract(bRd.multiply(xAverageValue));
        double mRd = Math.exp(b0.doubleValue());
        HashMap<String, BigDecimal> map = new HashMap<>();
        map.put("mrd", BigDecimal.valueOf(mRd));
//        log.info("mrd的值:{}",BigDecimal.valueOf(mRd));
        map.put("brd", bRd);
//        log.info("brd的值:{}",bRd);
        return map;
    }

    @Override
    public RestResponse getByRegion(List<EstimateParam> list,String fortification) {
        ArrayList<BuildingVulnerabilityVo> resultList = new ArrayList<>();
        if(PlatformObjectUtils.isEmpty(list) || list.size()!=5){
            proData(list);
        }
        List<EstimateParam> esList = list.stream()
                .filter(obj -> obj.getStructureType() != null)
                .collect(Collectors.toList());

        for (EstimateParam param : esList) {
            param.setFortification(fortification);
            if(param.getStructureType().equals("其他")){
                param.setFortification("未设防");
            }
            //时间格式化
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            //从数据库查出来矩阵数据    生成的易损性数据 and 概率地震矩阵或曲线 and 易损性信息矩阵或曲线
            MatchingParam matchingParam = new MatchingParam();
            BeanUtil.copyPropertiesIgnoreEmpty(param, matchingParam);
            List<CbvInfoEntity> basicLibraryList = customVulnerabilityRepository.queryBasicLibraryData(matchingParam);
            HashMap<String, List<GenerateVulnerabilityMatrixVo>> resultMap = new HashMap<>();
            if (PlatformObjectUtils.isNotEmpty(basicLibraryList)) {
                for (CbvInfoEntity it : basicLibraryList) {
                    //生成的易损性数据
                    if (it.getDataType().equals(FxfzConstants.CZT_SCYSX_INFO)) {
                        List<GenerateVulnerabilityMatrixVo> dataList = null;
                        CztBuildingMatrixEntity entity = svAnalysisRepository.getBuildingMatrixById(it.getPId());
                        String spilt = SvAnalysisServiceImpl.spilt(entity.getDataSourcesIds());
                        String[] intensityArr = {"6度", "7度", "8度", "9度", "10度"};
                        //震害数据矩阵
                        if (entity.getMatrixType() == 1) {
                            dataList = svAnalysisService.getDataList(spilt, intensityArr);
                            resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), dataList);
                        }
                        // 2 预测数据矩阵  3 筛选数据矩阵
                        if (entity.getMatrixType() == 2 || entity.getMatrixType() == 3) {
                            dataList = svAnalysisService.getPredictiveData(spilt, intensityArr, entity.getMatrixType());
                            resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), dataList);
                        }
                    }
                    //概率地震
                    if (it.getDataType().equals(FxfzConstants.CZT_GLDZ_INFO)) {
                        List<CpvResultEntity> dataList = bacInformationRepository.getCpvResultEntityByCpviId(it.getPId());
                        ArrayList<CbvInfoCurveValueEntity> curveList = new ArrayList<>();
                        dataList.forEach(gv -> {
                            CbvInfoCurveValueEntity entity = new CbvInfoCurveValueEntity();
                            entity.setBreakState(gv.getBreakState());
                            entity.setFim(gv.getFim());
                            entity.setIm(gv.getIm());
                            curveList.add(entity);
                        });
                        List<GenerateVulnerabilityMatrixVo> resultData = getProcessData(curveList);
                        resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), resultData);
                    }
                    //易损性信息
                    if (it.getDataType().equals(FxfzConstants.CZT_JZWYSX_INFO)) {
                        List<CbvInfoMatrixValueEntity> matrixList = svAnalysisRepository.getInfoMatrixById(it.getPId());
                        ArrayList<GenerateVulnerabilityMatrixVo> matrixDataList = new ArrayList<>();
                        if (matrixList != null) {
                            matrixList.forEach(ma -> {
                                GenerateVulnerabilityMatrixVo entity1 = new GenerateVulnerabilityMatrixVo();
                                entity1.setDamage("基本完好");
                                entity1.setIntensity(ma.getIntensity());
                                entity1.setRate(ma.getBasicallyIntact().toString() + "%");
                                matrixDataList.add(entity1);
                                GenerateVulnerabilityMatrixVo entity2 = new GenerateVulnerabilityMatrixVo();
                                entity2.setDamage("轻微破坏");
                                entity2.setIntensity(ma.getIntensity());
                                entity2.setRate(ma.getMinorDamage().toString() + "%");
                                matrixDataList.add(entity2);
                                GenerateVulnerabilityMatrixVo entity3 = new GenerateVulnerabilityMatrixVo();
                                entity3.setDamage("中等破坏");
                                entity3.setIntensity(ma.getIntensity());
                                entity3.setRate(ma.getModerateDamage().toString() + "%");
                                matrixDataList.add(entity3);
                                GenerateVulnerabilityMatrixVo entity4 = new GenerateVulnerabilityMatrixVo();
                                entity4.setDamage("严重破坏");
                                entity4.setIntensity(ma.getIntensity());
                                entity4.setRate(ma.getSeriousDamage().toString() + "%");
                                matrixDataList.add(entity4);
                                GenerateVulnerabilityMatrixVo entity5 = new GenerateVulnerabilityMatrixVo();
                                entity5.setDamage("倒塌");
                                entity5.setIntensity(ma.getIntensity());
                                entity5.setRate(ma.getCollapse().toString() + "%");
                                matrixDataList.add(entity5);
                            });
                            resultMap.put(it.getNumber() + "_" + sdf.format(it.getCreateTime()), matrixDataList);
                        }
                    }
                }
                //根据配比计算
                ArrayList<List<BigDecimal>> valueList = new ArrayList<>();
                if(param.getCsList().size()!=0){
                    valueList.add(param.getCsList());
                }
                if(param.getYearsList().size()!=0){
                    valueList.add(param.getYearsList());
                }
                if(param.getUseList().size()!=0){
                    valueList.add(param.getUseList());
                }

                List<BigDecimal> calculate = calculate(valueList);
                ArrayList<GenerateVulnerabilityMatrixVo> value = getValue(calculate, resultMap);
                if (value.size() != 0) {
                    Map<String, List<GenerateVulnerabilityMatrixVo>> collect = value.stream().collect(Collectors.groupingBy(GenerateVulnerabilityMatrixVo::getDamage));
                    collect.forEach((k,v)->{
                        BuildingVulnerabilityVo entity = new BuildingVulnerabilityVo();
                        entity.setProvince(param.getProvince());
                        entity.setCity(param.getCity());
                        entity.setPrefecture(param.getCounty());
                        entity.setStructureType(StructureTypeConstant.getConstant(param.getStructureType()));
                        if(PlatformObjectUtils.isNotEmpty(param.getStructureType1())){
                            entity.setStructureType(StructureTypeConstant.getConstant(param.getStructureType()+"-"+param.getStructureType1()));
                        }
                        entity.setDestroy(k);
                        for (GenerateVulnerabilityMatrixVo item : v) {
                            if(item.getIntensity().equals("6度")){
                                entity.setSix(new BigDecimal(parsePercentage(item.getRate())*0.01));
                            }
                            if(item.getIntensity().equals("7度")){
                                entity.setSeven(new BigDecimal(parsePercentage(item.getRate())*0.01));
                            }
                            if(item.getIntensity().equals("8度")){
                                entity.setEight(new BigDecimal(parsePercentage(item.getRate())*0.01));
                            }
                            if(item.getIntensity().equals("9度")){
                                entity.setNine(new BigDecimal(parsePercentage(item.getRate())*0.01));
                            }
                            if(item.getIntensity().equals("10度")){
                                entity.setTen(new BigDecimal(parsePercentage(item.getRate())*0.01));
                            }
                        }
                        resultList.add(entity);
                    });
                }
            }
        }
        return RestResponse.succeed(resultList);
    }

    /**
     * 默认配比
     *
     * @param value
     * @param count
     * @return
     */
    private ArrayList<BigDecimal> defaultRatio(BigDecimal value, Integer count) {
        ArrayList<BigDecimal> list = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            list.add(value);
        }
        return list;
    }

    private void proData(List<EstimateParam> list) {
        String strs = "钢结构,钢筋混凝土结构,砌体结构,木结构,其他";
        for (String str : strs.split(",")) {
            EstimateParam param = new EstimateParam();
            ArrayList<BigDecimal> csList = new ArrayList<>();
            ArrayList<BigDecimal> useList = new ArrayList<>();
            ArrayList<BigDecimal> yearList = new ArrayList<>();

            boolean steel = list.stream()
                    .anyMatch(obj -> {
                        if (obj.getStructureType() != null && !obj.getStructureType().isEmpty()) {
                            return obj.getStructureType().contains(str);
                        }
                        return false;
                    });
            if (!steel) {
                if (str.equals("钢结构") || str.equals("钢筋混凝土结构") ) {
                    if(str.equals("钢筋混凝土结构")){
                        param.setStructureType1("框架结构");
                    }
                    csList = defaultRatio(BigDecimal.valueOf(0.3333333333), 3);
                    useList = defaultRatio(BigDecimal.valueOf(0.0909090909), 11);
                    yearList = defaultRatio(BigDecimal.valueOf(0.1666666667), 6);
                }else if(str.equals("砌体结构")){
                    param.setStructureType1("砖混结构");
                    csList = defaultRatio(BigDecimal.valueOf(0.5), 2);
                    useList = defaultRatio(BigDecimal.valueOf(0.0909090909), 11);
                    yearList = defaultRatio(BigDecimal.valueOf(0.1666666667), 6);
                } else if(str.equals("木结构") || str.equals("其他")){
                    useList = defaultRatio(BigDecimal.valueOf(0.3333333333), 3);
                    yearList = defaultRatio(BigDecimal.valueOf(0.1666666667), 6);
                }
                param.setProvince(list.get(0).getProvince());
                param.setCity(list.get(0).getCity());
                param.setCounty(list.get(0).getCounty());
                param.setCsList(csList);
                param.setUseList(useList);
                param.setYearsList(yearList);
                param.setStructureType(str);
                list.add(param);
            }
        }
    }
}
